package com.example.crawlerjava.service.command.impl;

import cn.hutool.core.util.ObjectUtil;
import com.example.crawlerjava.entity.VideoDetailEntity;
import com.example.crawlerjava.service.command.FFmpegCmd;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import java.io.*;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Stream;

@Slf4j
@Service
public class FFmpegCmdImpl implements FFmpegCmd {
    @Override
    public String mergeTsVideo(String m3u8FilePath) {
        String cmd = "ffmpeg -allowed_extensions ALL -i " + m3u8FilePath + " -c copy " + m3u8FilePath.replace(".m3u8", ".mp4");
        try {
            Process process = Runtime.getRuntime().exec(cmd);

            ProcessBuilder processBuilder = new ProcessBuilder(cmd.split(" "));
            processBuilder.redirectErrorStream(true); // 将错误输出合并到标准输出

            // 读取输出流
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
            String line;
            while ((line = reader.readLine()) != null) {
                log.info(line);
            }
            int exitCode = process.waitFor();
            log.info("合并ts文件结果值:{}", exitCode);
        } catch (Exception e) {
            log.info("合并ts文件失败:{}", m3u8FilePath);
        }
        return m3u8FilePath.replace(".m3u8", ".mp4");
    }

    @Override
    public List<VideoDetailEntity> getTsVideoDetail(String videoPath) {
        if (ObjectUtil.isEmpty(videoPath)) {
            return Collections.emptyList();
        }
        Path directory = Paths.get(videoPath);
        try (Stream<Path> walk = Files.walk(directory)) {
            // 获取目录下的所有文件
            List<Path> fileList = walk.filter(path -> !path.equals(directory))
                    .toList();
            List<String> list = fileList.stream()
                    .filter(path -> path.toString().endsWith(".ts"))
                    .sorted(Comparator.comparing(path -> path.getFileName().toString()))
                    .map(Path::toString)
                    .toList();
            return getTsFileDurations(list);
        } catch (Exception e) {
            log.error("获取ts文件列表失败:{}", videoPath, e);
        }
        return Collections.emptyList();
    }


    private static List<VideoDetailEntity> getTsFileDurations(List<String> tsFilePaths) throws IOException, InterruptedException {
        List<VideoDetailEntity> videoDetailEntities = new ArrayList<>(tsFilePaths.size());


        for (String filePath : tsFilePaths) {
            ProcessBuilder pb = new ProcessBuilder("ffmpeg", "-i", filePath, "-hide_banner");
            pb.redirectErrorStream(true); // 合并标准错误和标准输出

            Process process = pb.start();
            BufferedReader reader = new BufferedReader(new InputStreamReader(process.getInputStream()));

            String line;
            Pattern pattern = Pattern.compile("Duration: (\\d{2}):\\d{2}:\\d{2}\\.\\d{2}, start:");

            VideoDetailEntity detailEntity = new VideoDetailEntity();
            detailEntity.setVideoFilePath(filePath);
            while ((line = reader.readLine()) != null) {
                Matcher matcher = pattern.matcher(line);
                if (matcher.find()) {
                    String durationStr = matcher.group(1);
                    long durationSec = parseDuration(durationStr);
                    detailEntity.setVideoDuration(durationSec);
                    break; // 只需要第一个匹配项
                }
            }
            videoDetailEntities.add(detailEntity);
            process.waitFor(); // 等待子进程结束
        }

        return videoDetailEntities;
    }

    private static long parseDuration(String durationStr) {
        String[] parts = durationStr.split(":");
        int hours = Integer.parseInt(parts[0]);
        int minutes = Integer.parseInt(parts[1]);
        int seconds = Integer.parseInt(parts[2]);

        return TimeUnit.HOURS.toSeconds(hours) + TimeUnit.MINUTES.toSeconds(minutes) + seconds;
    }

    private static void generateM3u8File(Map<String, Long> durationMap) throws IOException {
        try (BufferedWriter writer = new BufferedWriter(new FileWriter("output.m3u8"))) {
            writer.write("#EXTM3U\n");
            writer.write("#EXT-X-VERSION:3\n");
            writer.write("#EXT-X-TARGETDURATION:10\n");
            writer.write("#EXT-X-MEDIA-SEQUENCE:0\n");

            int sequenceNumber = 0;
            for (Map.Entry<String, Long> entry : durationMap.entrySet()) {
                String filePath = entry.getKey();
                long durationSec = entry.getValue();
                writer.write("#EXTINF:" + durationSec + ",\n");
                writer.write(filePath + "\n");
                sequenceNumber++;
            }

            writer.write("#EXT-X-ENDLIST\n");
        }
    }
}
